﻿import flash.display.FrameLabel;
import flash.display.Graphics;
import mx.rpc.http.HTTPService;
import mx.rpc.events.ResultEvent;
import mx.managers.PopUpManager;
import mx.collections. *;
import mx.controls. *;
import com.esri.ags.Map;
import com.esri.ags.geometry.Extent;
import mx.collections.ArrayCollection;
import com.adobe.serialization.json.JSON;
import com.uprr.app.tnm.events.AppEvent;
import com.uprr.app.tnm.events.EventBus;

import mx.collections.SortField;
import mx.collections.Sort;
import mx.events.*;

import com.esri.ags.geometry.MapPoint;     
import com.esri.ags.geometry.Extent;   
import com.esri.ags.geometry.Geometry;            
import com.esri.ags.Graphic;            
import com.esri.ags.symbol.SimpleMarkerSymbol;
import com.esri.ags.symbol.InfoSymbol;
import com.esri.ags.symbol.InfoSymbol;

import com.uprr.app.tnm.model.Model;
import com.esri.ags.utils.*;
import mx.managers.CursorManager;

import com.esri.ags.geometry.Polyline;

import flash.net.*;

[Bindable]
private var trnSymbArray:ArrayCollection = new ArrayCollection();

[Bindable]
private var trnDayArray:ArrayCollection = new ArrayCollection();

public var stnGraphicList:ArrayCollection = new ArrayCollection();

[Bindable]
private var trnSchedule:Object;

private var delayTimer:Timer; 
 
	private function arvlDateFmt( item:Object, column:DataGridColumn):String
			{
				return df.format( item.actlArvlDt);
			}
	private function depDateFmt( item:Object, column:DataGridColumn):String
			{
				return df.format( item.actlDepDt);
			}

	/**
	 * initialization
	 */		
	private function init():void {
		EventBus.addEventListener (AppEvent.STN_DOUBLECLICK, mapToStn);
		CursorManager.setBusyCursor ();
		autoComplete.enabled = false;
		loadTrainSymbolList();		
	}
	
	/**
	 *  When a stn is clicked
	 * @param	e
	 */
	private function mapToStn(e : AppEvent):void {
		//Alert.show("click is captured");
		Model.getInstance().map.scale = 18036;
		var pnt:MapPoint = new MapPoint(e.data.x, e.data.y);
		Model.getInstance().map.centerAt(pnt);
	}
	
	private function doBUQuery():void {
		var symb:String = autoComplete.selectedItem.trnSymb as String;	
		var day:String = trnDay.selectedItem.trnDay as String;
		//var u:URLRequest = new URLRequest("http://home.www.uprr.com/tfe/secure/standalone_functions/index.shtml?BU "+symb+" "+day);
		var u:URLRequest = new URLRequest("http://home.www.uprr.com/tfe/secure/function.jas?service=tcs_command&standaloneResult=true&tcs_command=BU " + symb + " " + day);
		navigateToURL(u,"_blank");
	}
	
	
	/**
	 *  Load distinctive train symbol for autoComplete at stratup
	 */
	private function loadTrainSymbolList():void {
	// disable caching
	var rnd : Number = Math.round(Math.random()*1000);
	var httpRequest:HTTPService =new HTTPService();
		httpRequest.url="GetTrainSymbList?x="+rnd;
		
	var parameters:Object=new Object();
	parameters.action="load";
	httpRequest.request=parameters;
	httpRequest.resultFormat="text";
	httpRequest.addEventListener(ResultEvent.RESULT, trainSymbResulteHandler);
	httpRequest.addEventListener("fault", serviceFaultHandler);
	httpRequest.send();
}

	/**
	 * @param	trnSymb
	 */
	private function loadTrainDayList(trnSymb:String):void {
	CursorManager.setBusyCursor ();	
	// disable caching
	var rnd : Number = Math.round(Math.random()*1000);
	var httpRequest:HTTPService =new HTTPService();
		httpRequest.url="GetTrainDayList?x="+rnd;
		
	var parameters:Object=new Object();
	parameters.trnSymb=trnSymb;
	httpRequest.request=parameters;
	httpRequest.resultFormat="text";
	httpRequest.addEventListener(ResultEvent.RESULT, trainDayResulteHandler);
	httpRequest.addEventListener("fault", serviceFaultHandler);
	httpRequest.send();
}

	/**
	 * ask for train route gps locations
	 * @param	crcList
	 */
	private function getTrainRouteGPS(crcList:Array):void {
	CursorManager.setBusyCursor ();	
	// disable caching
	var rnd : Number = Math.round(Math.random()*1000);
	var httpRequest:HTTPService =new HTTPService();
		httpRequest.url="GetTrainRouteGPS?x="+rnd;
	
	var cList:Object = { "crcList":crcList};	
	var jsonString:String = JSON.encode(cList);
	
	var parameters:Object=new Object();
	parameters.crcList = jsonString;
	httpRequest.request=parameters;
	httpRequest.resultFormat="text";
	httpRequest.addEventListener(ResultEvent.RESULT, trainRouteGPSResulteHandler);
	httpRequest.addEventListener("fault", serviceFaultHandler);
	httpRequest.send();
}

/**
 * Draw train route geometry
 * @param	event
 */
private function trainRouteGPSResulteHandler (event : ResultEvent) : void
{
	var rawData : String = String (event.result);	
	
	try 
	{
	/// CHnage !!!
		var gps : Object = (JSON.decode (rawData) as Object);
		var paths:Array = new Array();
		var routePaths:Array=gps.paths as Array
		
		for (var k:int; k < routePaths.length; k++){
		var xyArray:Array = routePaths[k].path;
		var pntArray:Array = new Array();
		for (var i:int = 0; i < xyArray.length; i++ ) {
			var mp:MapPoint = new MapPoint(xyArray[i].x, xyArray[i].y);
			pntArray.push(mp);
		}
		paths.push(pntArray);
		}
		
		var pLine:Polyline = new Polyline(paths);
	    
		var g:Graphic = new Graphic();
		g.geometry = pLine ;
		g.symbol = routeSymb;
		Model.getInstance ().graphicsLayer.add(g);
		stnGraphicList.addItem(g);
	
		CursorManager.removeBusyCursor ();
	 
	} catch (err : Error)
	{
		// we just ignoring to show route graphic, if something goes wrong
		
		/*
		var errorEvent : AppEvent = new AppEvent (AppEvent.APP_ERROR);
		errorEvent.data = "Error when loading train symbol list: "+err.toString();
		errorEvent.dispatch ();
		*/
	}
	
	/*
	// sort
	var dataSortField:SortField = new SortField();
	dataSortField.name = "trnSymb";
	var dataSort:Sort = new Sort();    
	dataSort.fields = [dataSortField];     
	trnSymbArray.sort = dataSort;    
	//refresh the collection to sort    
	trnSymbArray.refresh();
	*/
	
}

/**
 * Handel bookmark loading results
 * 
 * @usage   
 * @param   event 
 * @return  
 */

private function trainSymbResulteHandler (event : ResultEvent) : void
{
	var rawData : String = String (event.result);
	try 
	{
		var arr : Array = (JSON.decode (rawData) as Array);
		for (var i : int = 0; i < arr.length; i ++)
		{
			trnSymbArray.addItem ({"trnSymb":arr[i].trnSymb}); 
		}
		
		CursorManager.removeBusyCursor ();
		autoComplete.enabled = true;
	} catch (err : Error)
	{
		var errorEvent : AppEvent = new AppEvent (AppEvent.APP_ERROR);
		errorEvent.data = "Error when loading train symbol list: "+err.toString();
		errorEvent.dispatch ();
	}
	
	/*
	// sort
	var dataSortField:SortField = new SortField();
	dataSortField.name = "trnSymb";
	var dataSort:Sort = new Sort();    
	dataSort.fields = [dataSortField];     
	trnSymbArray.sort = dataSort;    
	//refresh the collection to sort    
	trnSymbArray.refresh();
	*/
	
}

private function trainDayResulteHandler (event : ResultEvent) : void
{
	var rawData : String = String (event.result);
	try 
	{
		var arr : Array = (JSON.decode (rawData) as Array);
		for (var i : int = 0; i < arr.length; i ++)
		{
			trnDayArray.addItem ({"trnDay":arr[i].day}); 
		}
		
		CursorManager.removeBusyCursor ();
	} catch (err : Error)
	{
		var errorEvent : AppEvent = new AppEvent (AppEvent.APP_ERROR);
		errorEvent.data = "Error when loading train day list: "+err.toString();
		errorEvent.dispatch ();
	}
}

// when something goes wrong for all HTTP services
private function serviceFaultHandler (event : Event) : void
{
	var errorEvent : AppEvent = new AppEvent (AppEvent.APP_ERROR);
		errorEvent.data = "Error when loading data";
		errorEvent.dispatch ();
}

// auto_complete
private function handleSearchChange():void 
			{
				if (delayTimer != null && delayTimer.running) 
				{
					delayTimer.stop();
				}
				
				if (autoComplete.searchText.length > 2 && trnSymbArray.length == 0) 
				{
					// if you remove below line then it kind of works
					// but it is more correct to remove all data
					// before repopulate. Really it is just holding
					// on to stale data
					trnSymbArray.removeAll();
					delayTimer = new Timer( 500, 1 );
					delayTimer.addEventListener(TimerEvent.TIMER, showComboAll);
					delayTimer.start();
					
					autoComplete.enabled = false;
				}
			}
			
private function showComboAll( event:TimerEvent ):void
			{
				autoComplete.enabled = true;
				autoComplete.search();
			}

/**
 *  when an item is selected
 */			
private function handleAutoCompleteChange():void
			{
				try 
				{
					// remove stns, is symb changed
					if (trnSchedule !=null)
						trnSchedule = null;
					removeStnDisplay();	
					var item:Object = autoComplete.selectedItem;
					if (trnDayArray!=null)
						trnDayArray.removeAll();
					if (item!=null)
						loadTrainDayList(item.trnSymb);
					
				} catch (err : Error)
				{
				var errorEvent : AppEvent = new AppEvent (AppEvent.APP_ERROR);
				errorEvent.data = "Error on AutoComplete: "+err.toString();
				errorEvent.dispatch ();
			}

}		
			
private function onTrnDayChange(event : Event):void {
				
}

/**
 *  Handler for submit button
 */
private function trackTrain():void {
	    CursorManager.setBusyCursor ();
		
		var symb:String = autoComplete.selectedItem.trnSymb as String;	
		var day:String = trnDay.selectedItem.trnDay as String;
		
		var rnd : Number = Math.round(Math.random()*1000);
		var httpRequest:HTTPService =new HTTPService();
		httpRequest.url="GetTrainSchedule?x="+rnd;
		
		var parameters:Object=new Object();
		parameters.trnSymb=symb;
		parameters.trnDay = day;
	
		httpRequest.request=parameters;
		httpRequest.resultFormat="text";
		httpRequest.addEventListener(ResultEvent.RESULT, trnStnListLoaderResulteHandler);
		httpRequest.addEventListener("fault", serviceFaultHandler);
		httpRequest.send();
		//Alert.show("Train:"+symb+day);
}

/**
 * @param	event
 */
 private function trnStnListLoaderResulteHandler (event : ResultEvent) : void
{
	var rawData : String = String (event.result);
	try 
	{
		trnSchedule=(JSON.decode (rawData) as Object);
		drawSchStns();
		
		var arr : Array = trnSchedule.trnStnList;
		var crcList:Array = new Array();
		for (var i : int = 0; i < arr.length; i ++)
		{
			crcList[i]=arr[i].rptgCrc7; 
		}
				
		getTrainRouteGPS(crcList);
		
	} catch (err : Error)
	{
		var errorEvent : AppEvent = new AppEvent (AppEvent.APP_ERROR);
		errorEvent.data = "Error when loading train station list: "+err.toString();
		errorEvent.dispatch ();
	}
}

/**
 *  Draw Scheduled stations
 */

// always add the current train Location at last, so it show on the top 
private var curLoc:Graphic;

private function drawSchStns():void {
	try 
	{
	var passingArray:Array = new Array();	
	// to highlight
	Model.getInstance().curCirc7 = trnSchedule.curCrc7;
	var sms:SimpleMarkerSymbol = new SimpleMarkerSymbol();
	sms.style = "circle";
	sms.color = 0xFFFF00;
	sms.size = 18;
	sms.alpha = 0.9;

	var stnList:Array = trnSchedule.trnStnList as Array;
 	/**
 	 * Why 
	 * for (var stn:Object in stnList)
	 * 
	 * Does not work !!!?
	 * 
 	 */	
	var n:int = 0;
	for (var i : int = 0; i < stnList.length; i ++){
		var pnt:MapPoint = new MapPoint(); 
		pnt.x = stnList[i].lon as Number;
		pnt.y = stnList[i].lat as Number;

		var g:Graphic = new Graphic();
		g.geometry = pnt;
		
		var infoSymb:InfoSymbol = new InfoSymbol();
		//Alert.show(trnSchedule.curCrc7 as String);
		
		// 1st visit of the stn
		if (passingArray[stnList[i].rptgCrc7] != stnList[i].rptgCrc7 ) {
				passingArray[stnList[i].rptgCrc7] = stnList[i].rptgCrc7;
				
		if (n == 0) {
			if (stnList[i].rptgCrc7 == trnSchedule.curCrc7)	{
			
				g.symbol = curStnSymb;
			}
			else
				g.symbol = startStnSymb;
		}
		else if (n==stnList.length-1){
		 	if (stnList[i].rptgCrc7 == trnSchedule.curCrc7)	
				g.symbol = curStnSymb;
			else	
				g.symbol = endStnSymb;
		}
		else {
			if (stnList[i].rptgCrc7 == trnSchedule.curCrc7)	
				g.symbol = curStnSymb;
			else
				g.symbol = passingStnSymb;
		} 
		} else { // 2nd visit of the stn
			if (n == 0) {
			if (stnList[i].rptgCrc7 == trnSchedule.curCrc7)	{
			
				g.symbol = curStnSymbR;
			}
			else
				g.symbol = startStnSymbR;
		}
		else if (n==stnList.length-1){
		 	if (stnList[i].rptgCrc7 == trnSchedule.curCrc7)	
				g.symbol = curStnSymbR;
			else	
				g.symbol = endStnSymbR;
		}
		else {
			if (stnList[i].rptgCrc7 == trnSchedule.curCrc7)	
				g.symbol = curStnSymbR;
			else
				g.symbol = passingStnSymbR;
		} 
		}
		
		g.attributes = { "circ7":stnList[i].rptgCrc7, "seq":stnList[i].stnSeqNbr};
		n++;
		
		stnGraphicList.addItem(g);
		
		if (stnList[i].rptgCrc7 == trnSchedule.curCrc7)	{
				curLoc = g; // add cur loc later
		} else{			
				Model.getInstance ().graphicsLayer.add(g);
			}
	}
		
		// now add the cur loc on top
		Model.getInstance ().graphicsLayer.add(curLoc);
	
		/**
		 * Always use ArrayCollection when possible !
		 */
		var ext:Extent = GraphicUtil.getGraphicsExtent(stnGraphicList.toArray());
		Model.getInstance().map.extent = ext.expand(1.5);
		CursorManager.removeBusyCursor ();
		
	} catch (err : Error)
	{
		var errorEvent : AppEvent = new AppEvent (AppEvent.APP_ERROR);
		errorEvent.data = "Error when drawing schedule stations: "+err.toString();
		errorEvent.dispatch ();
	}
}

private function removeStnDisplay():void {
	
		for (var i:int = 0; i < stnGraphicList.length; i++ ) {
			Model.getInstance ().graphicsLayer.remove( stnGraphicList[i] as Graphic);	
		}
		stnGraphicList.removeAll();
}


// double click handler
protected function stnDoubleClickHandler(event:ListEvent):void {
	var lat:Number = event.currentTarget.selectedItem.lat;
	var lon:Number = event.currentTarget.selectedItem.lon;
	
	var dcEvent : AppEvent = new AppEvent (AppEvent.STN_DOUBLECLICK);
	dcEvent.data = { "x":lon, "y":lat };
	dcEvent.dispatch ();
}

private function stnGridInit(event:FlexEvent):void {
	//Alert.show("enable grid double click");
	event.currentTarget.itemRenderer.properties = {doubleClickEnabled:true};
}


